package com.ai_daily.aitiantian;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.Image;
import android.media.ImageReader;
import android.os.Environment;
import android.util.Log;
import android.view.Surface;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;

import com.ai_daily.aitiantian.core.util.MyLogger;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;

public class CameraUtil {
    private static final String TAG = "CameraUtil";

    // 后台拍照保存路径，也是上传图片的路径
    private String mImgOriginalPath = "null";

    private OnTakePhotoListener mOnTakePhotoListener;

    // 照片路径
    private String IMG_FILE_PATH
            = Environment.getExternalStoragePublicDirectory("DCIM").getAbsolutePath() + "/Camera";

    private CameraDevice mCamera;
    private String mCameraId;
    private CaptureRequest.Builder mCaptureRequestBuilder;

    private Context mContext;

    public CameraUtil() {
    }

    public static CameraUtil getCameraInstance() {
        return CameraUtilHolder.cameraUtil;
    }

    public static class CameraUtilHolder {
        public static CameraUtil cameraUtil = new CameraUtil();
    }

    /**
     * 开始预览
     * 打开相机---设置相机参数---打开预览界面
     */
    private void startPreview(Context context) {
        Log.d(TAG, "[startPreview] >> begin. test");
        if (mCamera != null) {
            mCamera.close();
            mCamera = null;
        }
        try {
            CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
            mCameraId = getCameraId(manager); // 获取优先使用的相机ID
            if (mCameraId == null) {
                MyLogger.info(TAG + ".Debug", "没有可用的相机");
                return;
            }
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                MyLogger.info(TAG + ".Debug", "无相机权限");
                return;
            }
            manager.openCamera(mCameraId, stateCallback, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放相机资源
     * 拍照完成后释放相机资源
     */
    private void releaseCamera() {
        if (mCamera != null) {
            mCamera.close();
            mCamera = null;
        }
    }

    /**
     * 开始拍照
     */
    public void takePhoto(Context context, OnTakePhotoListener onTakePhotoListener) {
        Log.d(TAG, "takePhoto >> ");
        mContext = context;
        this.mOnTakePhotoListener = onTakePhotoListener;
        startPreview(context);
    }

    private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCamera = camera;
            try {
                mCaptureRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                ImageReader reader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1);
                mCaptureRequestBuilder.addTarget(reader.getSurface());

                // 设置自动对焦模式
                mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

                // 设置图像方向
                int rotation = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
                mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, getJpegOrientation(rotation));

                mCamera.createCaptureSession(Collections.singletonList(reader.getSurface()), new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession session) {
                        try {
                            session.capture(mCaptureRequestBuilder.build(), null, null);
                        } catch (CameraAccessException e) {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    }
                }, null);

                reader.setOnImageAvailableListener(readerListener, null);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            mCamera.close();
            mCamera = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            mCamera.close();
            mCamera = null;
        }
    };

    private final ImageReader.OnImageAvailableListener readerListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image image = null;
            try {
                image = reader.acquireLatestImage();
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);
                save(bytes);
            } finally {
                if (image != null) {
                    image.close();
                }
            }
        }

        private void save(byte[] bytes) {
            File file = new File(IMG_FILE_PATH, "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".jpg");
            FileOutputStream output = null;
            try {
                output = new FileOutputStream(file);
                output.write(bytes);
                mOnTakePhotoListener.onTakePhotoSuccess(file.getAbsolutePath());
                MyLogger.info(TAG + ".Debug", "拍照成功，路径：" + file.getAbsolutePath());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (null != output) {
                    try {
                        output.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    /**
     * 获取JPEG图像方向
     * @param rotation 设备旋转角度
     * @return JPEG方向
     */
    private int getJpegOrientation(int rotation) {
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }
        CameraManager manager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        try {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraId);
            int sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
            boolean isFrontFacing = characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT;
            if (isFrontFacing) {
                degrees = (sensorOrientation + degrees) % 360;
            } else {
                degrees = (sensorOrientation - degrees + 360) % 360;
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        return degrees;
    }

    /**
     * 获取相机ID，优先使用前置相机
     * @param manager CameraManager
     * @return 相机ID
     */
    private String getCameraId(CameraManager manager) throws CameraAccessException {
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                return cameraId; // 找到前置相机
            }
        }
        // 如果没有前置相机，则使用第一个可用的后置相机
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) {
                return cameraId; // 找到后置相机
            }
        }
        return null; // 没有找到可用的相机
    }

    interface OnTakePhotoListener {
        void onTakePhotoSuccess(String path);
    }
}